import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.ArrayList;
import java.util.List;

import javax.swing.JPanel;

/**
 * 坦克绘制区
 */
public class MyPanel extends JPanel implements KeyListener,Runnable{
    MyTank myTank = null;
    List<Enimy> enimes = new ArrayList<>();
    int enimeSize = 3;
    private boolean gameOver = false;

    public MyPanel() {
        myTank = new MyTank(100, 100);
        for (int i = 0; i < enimeSize; i++) {
            Enimy enimy = new Enimy(300 + i * 50, 200);
            enimes.add(enimy);
        }
        this.addKeyListener(this);
        this.setFocusable(true);   // 允许面板获取焦点
        this.requestFocusInWindow(); // 让面板请求焦点
    }

    public void paint(Graphics g) {
        super.paint(g);
        g.fillRect(0, 0, 1000 , 750);
        // 绘制坦克
        drawTank(myTank.getX(), myTank.getY(), g,myTank.getDirect(), 0);
        enimes.forEach(enimy -> {
            drawTank(enimy.getX(), enimy.getY(), g, enimy.getDirect(), 1);
            for(Shot shot : enimy.shots){
                if (shot!= null && shot.isLive) {
                    g.draw3DRect(shot.x, shot.y, 2, 2, false);
                }
            }
            //移除敌人死亡的子弹
            enimy.shots.removeIf(shot ->!shot.isLive);
        });
        // 绘制子弹
        for (Shot shot : myTank.shots) {
            if (shot != null && shot.isLive) {
                g.draw3DRect(shot.x, shot.y, 2, 2, false);
            }
        }
        // 移除死亡的子弹
        myTank.shots.removeIf(shot -> !shot.isLive);
        
        
    }

    /**
     * 绘制坦克
     * @param x 坦克的横坐标
     * @param y 坦克的纵坐标
     * @param g
     * @param direct 坦克方向
     * @param type 坦克类型
     */
    public void drawTank(int x,int y,Graphics g,int direct,int type){
        //颜色
        switch (type) {
            case 0:
                g.setColor(Color.cyan);
                break;
            case 1:
                g.setColor(Color.yellow);
                break;
        }
        //根据方向画形状
        switch (direct) {
            case 0:
                g.fill3DRect(x, y, 10, 60, false);
                g.fill3DRect(x + 10, y + 10, 20, 40, false);
                g.fill3DRect(x + 30, y, 10, 60, false);
                g.fillOval(x + 10, y + 20, 20, 20);
                g.drawLine(x + 20, y + 30, x + 20, y);
                break;
            case 1:
                g.fill3DRect(x, y, 60, 10, false);
                g.fill3DRect(x + 10, y + 10, 40, 20, false);
                g.fill3DRect(x, y + 30, 60, 10, false);
                g.fillOval(x + 20, y + 10, 20, 20);
                g.drawLine(x + 30, y + 20, x + 60, y + 20);
                break;
            case 2:
                g.fill3DRect(x, y, 10, 60, false);
                g.fill3DRect(x + 10, y + 10, 20, 40, false);
                g.fill3DRect(x + 30, y, 10, 60, false);
                g.fillOval(x + 10, y + 20, 20, 20);
                g.drawLine(x + 20, y + 30, x + 20, y + 60);
                break;
            case 3:
                g.fill3DRect(x, y, 60, 10, false);
                g.fill3DRect(x + 10, y + 10, 40, 20, false);
                g.fill3DRect(x, y + 30, 60, 10, false);
                g.fillOval(x + 20, y + 10, 20, 20);
                g.drawLine(x + 30, y + 20, x, y + 20);
                break;
        }

    }

    @Override
    public void keyTyped(KeyEvent e) {
    }

    @Override
    public void keyPressed(KeyEvent e) {
    // tank 移动
    if (e.getKeyCode() == KeyEvent.VK_W) {
        myTank.setDirect(0);
        if (myTank.getY() > 0) {
            myTank.setY(myTank.getY() - 20); // 向上移动
        }
    } else if (e.getKeyCode() == KeyEvent.VK_D) {
        myTank.setDirect(1);
        if (myTank.getX() + 60 < 1000) {
            myTank.setX(myTank.getX() + 20); // 向右移动
        }
    } else if (e.getKeyCode() == KeyEvent.VK_S) {
        myTank.setDirect(2);
        if (myTank.getY() + 60 < 750) {
            myTank.setY(myTank.getY() + 20); // 向下移动
        }
    } else if (e.getKeyCode() == KeyEvent.VK_A) {
        myTank.setDirect(3);
        if (myTank.getX() > 0) {
            myTank.setX(myTank.getX() - 20); // 向左移动
        }
    }
    this.repaint(); // 重新绘制，更新坦克位置

    // 发射子弹
    if (e.getKeyCode() == KeyEvent.VK_J) {
        myTank.shotEnemy();
    }
}

    @Override
    public void keyReleased(KeyEvent e) {
    }

    // 检测子弹是否击中敌方坦克
    public void hitTank() {
        for (Shot shot : myTank.shots) {
            if (shot.isLive) {
                for (int i = enimes.size() - 1; i >= 0; i--) {
                    Enimy enimy = enimes.get(i);
                    // 根据坦克方向判断碰撞区域
                    int tankWidth = (enimy.getDirect() == 1 || enimy.getDirect() == 3) ? 60 : 40;
                    int tankHeight = (enimy.getDirect() == 1 || enimy.getDirect() == 3) ? 40 : 60;
                    
                    if (shot.x > enimy.getX() && shot.x < enimy.getX() + tankWidth &&
                        shot.y > enimy.getY() && shot.y < enimy.getY() + tankHeight) {
                        shot.isLive = false;
                        enimes.remove(i);
                    }
                }
            }
        }
    }

    // 检测敌方子弹是否击中我方坦克
    public void hitMyTank() {
        for (Enimy enimy : enimes) {
            for (Shot shot : enimy.shots) {
                if (shot.isLive) {
                    // 根据坦克方向判断碰撞区域
                    int tankWidth = (myTank.getDirect() == 1 || myTank.getDirect() == 3) ? 60 : 40;
                    int tankHeight = (myTank.getDirect() == 1 || myTank.getDirect() == 3) ? 40 : 60;
                    
                    if (shot.x > myTank.getX() && shot.x < myTank.getX() + tankWidth &&
                        shot.y > myTank.getY() && shot.y < myTank.getY() + tankHeight) {
                        shot.isLive = false;
                        gameOver = true;
                    }
                }
            }
        }
    }

    @Override
    public void run() {// 每隔100毫秒重绘一次，子弹移动
        while (!gameOver) {
            try {
                Thread.sleep(10);
                //2%的概率发射子弹
                for(Enimy enimy : enimes){
                    if(Math.random() < 0.02){
                        enimy.shotEnemy();
                    }
                    if(Math.random() < 0.01){
                        enimy.setDirect((int)(Math.random() * 4));
                    }
                    // 根据方向移动敌方坦克
                    switch(enimy.getDirect()) {
                        case 0: // 上
                            if(enimy.getY() > 0) {
                                enimy.setY(enimy.getY() - 1);
                            } else {
                                enimy.setDirect((int)(Math.random() * 4));
                            }
                            break;
                        case 1: // 右
                            if(enimy.getX() + 60 < 1000) {
                                enimy.setX(enimy.getX() + 1);
                            } else {
                                enimy.setDirect((int)(Math.random() * 4));
                            }
                            break;
                        case 2: // 下
                            if(enimy.getY() + 60 < 750) {
                                enimy.setY(enimy.getY() + 1);
                            } else {
                                enimy.setDirect((int)(Math.random() * 4));
                            }
                            break;
                        case 3: // 左
                            if(enimy.getX() > 0) {
                                enimy.setX(enimy.getX() - 1);
                            } else {
                                enimy.setDirect((int)(Math.random() * 4));
                            }
                            break;
                    }
                }    
                // 检测子弹是否击中敌方坦克
                hitTank();
                // 检测敌方子弹是否击中我方坦克
                hitMyTank();
                if (gameOver) {
                    System.exit(0);
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            this.repaint();
        }
    }
}